package com.mantisframework.core.base.dao;

import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import jodd.util.StringUtil;

import org.apache.commons.beanutils.BeanUtils;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.stereotype.Repository;

import com.mantisframework.core.utils.JDBCUtil;
import com.mantisframework.core.utils.Utils;

/**
 * 功能： 基本dao实现类 作者：马东东 时间：2010-03-23
 */
@Repository
@Lazy(true)
public class BaseDao<T> extends HibernateDaoSupport implements IBaseDao<T> {

	  @Resource(name="sessionFactory")
	  public void setMySessionFactory(SessionFactory paramSessionFactory)
	  {
	    setSessionFactory(paramSessionFactory);
	  }

	public int getCount(T pojo) {
		int count = 0;
		Object obj = this.getHibernateTemplate().find(
				"select count(*) from " + pojo.getClass().getName()).get(0);
		count=new Integer(obj.toString());
		return count;
	}
	
	public int getCount(T pojo, String condition) {
		int count = 0;
		Object obj =  this.getHibernateTemplate().find(
				"select count(*) from " + pojo.getClass().getName() + " "
						+ condition).get(0);
		count=new Integer(obj.toString());
		return count;
	}
	//add by guozheng 
	public int getCount( String condition) {
		int count = 0;
		Object obj =  this.getHibernateTemplate().find(
				"select count(a) " 
						+ condition).get(0);
		count=new Integer(obj.toString());
		return count;
	}

	public int getTotalPage(T pojo, String condition, int numPerPage) {
		int totalPage = 1;
		int count = getCount(pojo, condition);
		if(numPerPage>0) {
			if(count%numPerPage>0&&count>0)
				totalPage = count/numPerPage+1;
			else
				totalPage = count/numPerPage;
		}
		return totalPage;
	}
	
	public int getTotalPage(String condition, int numPerPage) {
		int totalPage = 1;
		int count = getCount(condition);
		if(numPerPage>0) {
			if(count%numPerPage>0&&count>0)
				totalPage = count/numPerPage+1;
			else totalPage = count/numPerPage;
		}
		return totalPage;
	}
	
	@SuppressWarnings("unchecked")
	public List<T> getAll(T pojo, int index, int pageSize) {

		return this.getHibernateTemplate().findByExample(pojo, index, pageSize);
	}

	
	
	@SuppressWarnings("unchecked")
	public List<T> getAll(T pojo) {
		return this.getHibernateTemplate().findByExample(pojo);
	}

	
	@SuppressWarnings("unchecked")
	public List<T> getAll(final T pojo, final String condition) {
		List<T> list = this.getHibernateTemplate().executeFind(
				new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						Query query = session.createQuery("from "
								+ pojo.getClass().getName() + " " + condition);
						List<T> inList = null;
						try {
							inList = query.list();
						} catch (HibernateException e) {
							e.printStackTrace();
							inList = new ArrayList<T>();
						}
						return inList;
					}
				});

		return list;
	}

	@SuppressWarnings("unchecked")
	public List<T> getAll(final T pojo, final String condition,
			final int startIndex, final int pageSize) {

		List<T> list = this.getHibernateTemplate().executeFind(
				new HibernateCallback() {

					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						Query query = session.createQuery("from "
								+ pojo.getClass().getName() + " " + condition);
						query.setFirstResult(startIndex);
						if (pageSize > 0) {
							query.setMaxResults(pageSize);
						}
 						List<T> inList = null;
						try {
							inList = query.list();
						} catch (HibernateException e) {
							e.printStackTrace();
							inList = new ArrayList<T>();
						}
						return inList;
					}
				});

		return list;

	}
	@SuppressWarnings("unchecked")
	public List<T> getAll(final String condition,
			final int startIndex, final int pageSize) {

		List<T> list = this.getHibernateTemplate().executeFind(
				new HibernateCallback() {

					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						Query query = session.createQuery( "select a "+condition);
						query.setFirstResult(startIndex);
						if (pageSize > 0) {
							query.setMaxResults(pageSize);
						}
 						List<T> inList = null;
						try {
							inList = query.list();
						} catch (HibernateException e) {
							e.printStackTrace();
							inList = new ArrayList<T>();
						}
						return inList;
					}
				});

		return list;

	}

	
	
	@SuppressWarnings("unchecked")
	public T getById(Class<T> c, Serializable id) {

		return (T) this.getHibernateTemplate().get(c, id);
	}

	
	public T getById(T pojo, String conditon) {

		List<T> list = this.getAll(pojo, conditon, 0, 0);
		if (list.size() > 0) {
			return list.get(0);
		}
		return null;
	}
	
	public boolean save(T pojo) {

		try {
			this.getHibernateTemplate().save(pojo);
		} catch (DataAccessException e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	
	public boolean saveOrUpdate(final T pojo, final Serializable id) {

		@SuppressWarnings({ "unchecked", "rawtypes" })
		boolean flag = (Boolean) this.getHibernateTemplate().execute(
				new HibernateCallback() {

					@SuppressWarnings("unchecked")
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {

						T pojoBase = (T) session.get(pojo.getClass(), id);
						if (pojoBase == null) {
							try {
								pojoBase = (T) pojo.getClass().newInstance();
								BeanUtils.copyProperties(pojoBase, pojo);
								session.save(pojoBase);
							} catch (Exception e) {
								e.printStackTrace();
								return false;
							}

						} else {
							try {
								BeanUtils.copyProperties(pojoBase, pojo);
								session.update(pojoBase);
								session.flush();
							} catch (Exception e) {
								e.printStackTrace();
								return false;
							}
						}
						return true;
					}

				});

		return flag;
	}

	public boolean modify(T pojo) {

		try {
			this.getHibernateTemplate().update(pojo);
		} catch (DataAccessException e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	
	public int modify(final String hql) {
    Object obj=this.getHibernateTemplate().execute(new HibernateCallback(){

	public Object doInHibernate(Session session) throws HibernateException,
			SQLException {
		return session.createQuery(hql).executeUpdate();
	}});
		return new Integer(obj.toString());
	}

	public boolean modifyDynamic(final T pojo, final Serializable id) {

		return (Boolean) this.getHibernateTemplate().execute(
				new HibernateCallback() {

					@SuppressWarnings("unchecked")
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						T instance = (T) session.load(pojo.getClass(), id);
						try {
							BeanUtils.copyProperties(pojo, instance);
							session.merge(instance);
							session.update(instance);
							session.flush();
						} catch (Exception e) {
							e.printStackTrace();
							return false;
						}
						return true;
					}

				});
	}


	public boolean delete(T pojo) {

		try {
			this.getHibernateTemplate().delete(pojo);
		} catch (DataAccessException e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	
	public boolean query(final String hql) {

		return (Boolean) this.getHibernateTemplate().execute(
				new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						Query query = session.createQuery(hql);
						try {
							query.executeUpdate();
						} catch (HibernateException e) {
							e.printStackTrace();
							return false;
						}
						return true;
					}

				});
	}
	
	public List<?> query(final String hql, final int startIndex, final int pageSize) {

		return this.getHibernateTemplate().executeFind(new HibernateCallback() {

			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				Query query = session.createQuery(hql);
				query.setFirstResult(startIndex);
				if (pageSize > 0) {
					query.setMaxResults(pageSize);
				}
				List<?> list = null;
				try {
					list = query.list();
				} catch (HibernateException e) {
					e.printStackTrace();
					list = new ArrayList<Object>();
				}
				return list;
			}
		});
	}

	
	public boolean queryJDBCSql(final String sql) {

		return (Boolean) this.getHibernateTemplate().execute(
				new HibernateCallback() {

					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						try {
							Statement st = session.connection()
									.createStatement();
							st.execute(sql);
						} catch (Exception e) {
							e.printStackTrace();
							return false;
						}
						return true;
					}

				});

	}

	public int queryJDBCSqlCount(final String sql) {

		return (Integer) this.getHibernateTemplate().execute(
				new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						try {
							Statement st = session.connection()
									.createStatement();
							ResultSet rs = st.executeQuery(sql);
							while (rs.next()) {
								return rs.getInt(1);
							}
							return 0;
						} catch (Exception e) {
							e.printStackTrace();
							return 0;
						}
					}

				});
	}

	
	public List<?> queryJDBCSql(final String sql, final Class<?> instance)
			throws SQLException, IllegalAccessException,
			InvocationTargetException, InstantiationException {

		return this.getHibernateTemplate().executeFind(new HibernateCallback() {

			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				Statement st = session.connection().createStatement();
				ResultSet rs = st.executeQuery(sql);
				List<?> list = null;
				try {
					list = JDBCUtil.transTurnList(rs, instance);
				} catch (Exception e) {
					e.printStackTrace();
					list = new ArrayList<Object>();
				}
				return list;
			}
		});
	}
	
	public int batchDelete(T pojo, Map<String, Serializable[]> keyMap,
			int andORor, String otherCondtion) {
		
		String logic = " and ";
		if (andORor == 1) {
			logic = " or ";
		} else {
			andORor = 0;// 不为1即为0
		}
		
		int count = 0;
		
		if (keyMap.size() != 0) {
			
			StringBuffer hql = new StringBuffer("delete from "
					+ pojo.getClass().getName() + " where (");
			int header = 0;
			for (String key : keyMap.keySet()) {
				
				if (header != 0) {
					hql.append(logic);
				}
				header++;
				
				Serializable[] valueSet = keyMap.get(key);
				
				if (!Utils.isEmpty(valueSet)) {
					
					hql.append(key + " in (");
					
					int i = 1;
					for (Serializable ser : valueSet) {
						if (ser != null) {
							hql.append("'").append(ser).append("'");
						} else {
							hql.append(ser);
						}
						if (i < valueSet.length) {
							hql.append(",");
						}
						i++;
					}// for
					hql.append(" ) ");
				} else if (andORor == 0) {
					hql.append(" 1=1 ");
				} else {
					hql.append(" 1>1 ");
				}// if else
				
			}// for
			
			hql.append(" ) ");
			
			if (StringUtil.isNotEmpty(otherCondtion)) {
				hql.append(otherCondtion);
			}
			
			final String sql = hql.toString();
			
			count = (Integer) this.getHibernateTemplate().execute(
					new HibernateCallback() {
						
						public Object doInHibernate(Session session)
						throws HibernateException, SQLException {
							Query query = session.createQuery(sql);
							try {
								return query.executeUpdate();
							} catch (HibernateException e) {
								e.printStackTrace();
								return 0;
							}
						}
					});
			
		}// if
		return count;
	}
	public int delete(T pojo, String otherCondtion) {
			StringBuffer hql = new StringBuffer("delete from "
					+ pojo.getClass().getName() + " where 1=1 ");

			final String sql = hql.toString();

			int count = (Integer) this.getHibernateTemplate().execute(
					new HibernateCallback() {
						public Object doInHibernate(Session session)
								throws HibernateException, SQLException {
							Query query = session.createQuery(sql);
							try {
								return query.executeUpdate();
							} catch (HibernateException e) {
								e.printStackTrace();
								return 0;
							}
						}
					});

		return count;
	}

	public int execute(final String hql) {

		int count = (Integer) this.getHibernateTemplate().execute(
				new HibernateCallback() {
					public Object doInHibernate(Session session)
							 {
						Query query = session.createQuery(hql);
						try {
							return query.executeUpdate();
						} catch (HibernateException e) {
							e.printStackTrace();
							return -1;
						}
					}
				});

	return count;
	}

	public int batchModify(T pojo, Map<String, Serializable[]> keyMap,
			Map<String, Serializable> valueMap, int andORor,
			String otherCondtion) {

		String logic = " and ";
		if (andORor == 1) {
			logic = " or ";
		} else {
			andORor = 0;// 不为1即为0
		}

		int count = 0;
		int keySize = keyMap.size();
		int valueSize = valueMap.size();

		if (keySize * valueSize > 0) {

			StringBuffer hql = new StringBuffer("update "
					+ pojo.getClass().getName() + " set ");

			int i = 1;
			for (String key : valueMap.keySet()) {
				hql.append(key + "='" + valueMap.get(key)).append("' ");
				if (i < valueSize) {
					hql.append(",");
				}
				i++;
			}

			// where 条件
			hql.append(" where (");
			int header = 0;
			for (String key : keyMap.keySet()) {
				if (header != 0) {
					hql.append(logic);
				}
				header++;

				Serializable[] valueSet = keyMap.get(key);

				if (!Utils.isEmpty(valueSet)) {

					hql.append(key).append(" in (");
					int time = 1;
					Serializable[] keyset = keyMap.get(key);
					for (Serializable ser : keyset) {
						if (ser != null) {
							hql.append("'").append(ser).append("'");
						} else {
							hql.append(ser);
						}
						if (time < keyset.length) {
							hql.append(",");
						}
						time++;
					}
					hql.append(") ");
				} else if (andORor == 0) {
					hql.append(" 1=1 ");
				} else {
					hql.append(" 1>1 ");
				}// if else
			}
			hql.append(" ) ");

			if (StringUtil.isNotEmpty(otherCondtion)) {
				hql.append(otherCondtion);
			}

			final String sql = hql.toString();

			count = (Integer) this.getHibernateTemplate().execute(
					new HibernateCallback() {

						public Object doInHibernate(Session session)
								throws HibernateException, SQLException {
							Query query = session.createQuery(sql);
							try {
								return query.executeUpdate();
							} catch (HibernateException e) {
								e.printStackTrace();
								return 0;
							}
						}
					});
		}
		return count;
	}

	

	public Session getDaoSession() {
		return super.getSession();
	}

	public HibernateTemplate getDaoHibernateTemplate() {
		return super.getHibernateTemplate();
	}

}
